package com.bgds.sys.influx.serviceimpl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.bgds.sys.common.constant.BizConstant;
import com.bgds.sys.common.pagevo.SeriesVo;
import com.bgds.sys.common.utils.DateUtils;
import com.bgds.sys.config.influx.InfluxConfig;
import com.bgds.sys.influx.service.InfluxService;
import com.bgds.sys.influx.utils.InfluxUtils;
import com.bgds.sys.module.entity.DeviceDynamicAttr;
import com.bgds.sys.module.service.IDeviceDynamicAttrService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**


 /**
 * @Description influxDB 数据库操作封装类
 * @Author lj
 * @create: 2020-07-16 11:34
 */
@Service
@Slf4j
public class InfluxServiceImpl implements InfluxService {

    @Autowired
    private InfluxUtils influxUtils;



    @Override
    public List<SeriesVo> queryByForMap(String deviceCode, Long startTime, Long endTime, List<DeviceDynamicAttr> deviceDynamicAttrs) {
        //图表数据
        List<SeriesVo> chartData=new ArrayList<>();
        if (CollectionUtils.isEmpty(deviceDynamicAttrs)) {
            log.error("按attrIds数组批量查询失败,attrIds为null: "
                    + "startTime={}, endTime={}", startTime, endTime);
            return chartData;
        }
        StringBuilder sql=new StringBuilder();
        sql.append("select ");
        for(DeviceDynamicAttr attr:deviceDynamicAttrs){
            sql.append(" \""+attr.getEngName()+"\",");
        }
        sql.deleteCharAt(sql.length()-1);

        sql.append(" from \"" + deviceCode + "\"  where 1=1 ");
        linkTimeSql(sql, startTime, endTime);
        log.info("查询sql:"+sql.toString());
        List<Map<String, Object>> mapList=influxUtils.queryForMap(sql.toString());
        if(!CollectionUtils.isEmpty(mapList)){
            List<Map<String, Object>> dilutionList=dilution(mapList);
            //遍历每条数据
            for(Map<String, Object> map:dilutionList){
                String timeStr=String.valueOf(map.get("time"));
                long time=DateUtils.utcToTimeMillis(timeStr);
                //遍历每个值
                map.forEach((key,value)->{
                    if(!"time".equalsIgnoreCase(key)){
                        SeriesVo seriesVo= new SeriesVo();
                        DeviceDynamicAttr dda = deviceDynamicAttrs.stream().filter(item -> item.getEngName().equals(key)).findFirst().get();
                        if(!ObjectUtil.isEmpty(dda)){
                            seriesVo.setName(dda.getName());
                        }
                        DecimalFormat df = new DecimalFormat("#.00");
                        if(ObjectUtil.isNotEmpty(value)){
                            seriesVo.setValue(Double.valueOf(df.format(Double.valueOf(value.toString()))));
                        }else{
                            seriesVo.setValue(0.0);
                        }
                        seriesVo.setUnit(dda.getUnit());
                        seriesVo.setTime(time);
                        seriesVo.setEngName(dda.getEngName());
                        chartData.add(seriesVo);
                    }
                });
            }
        }else{
            return chartData;
        }
        return chartData;
    }
    /**
     * 稀释数据
     * @param maps
     * @return
     */
    private  List<Map<String, Object>> dilution(List<Map<String, Object>> maps){
        List<Map<String, Object>> dilutionSeriesVos=new ArrayList<>();
        int interval=(int)Math.ceil((float)maps.size()/2000);
        if(maps.size()>2000){
            for(int i=0;i<maps.size();i=i+interval){
                dilutionSeriesVos.add(maps.get(i));
            }
        }else{
            for(int i=0;i<maps.size();i++){
                dilutionSeriesVos.add(maps.get(i));
            }
        }
        return dilutionSeriesVos;
    }
    @Override
    public List<Map<String, Object>> queryByForMap(String measurement, List<DeviceDynamicAttr> deviceDynamicAttrs) {
        StringBuilder sql=new StringBuilder();
        sql.append("select LAST(");
        sql.append(deviceDynamicAttrs.get(0).getEngName());
        sql.append("),");
        for(DeviceDynamicAttr attr:deviceDynamicAttrs){
            sql.append(" \""+attr.getEngName()+"\",");
        }
        sql.deleteCharAt(sql.length()-1);

        sql.append(" from \"" + measurement + "\"  where 1=1 ");
        List<Map<String, Object>> mapList=influxUtils.queryForMap(sql.toString());
        return mapList;
    }

    /**
     * 拼接时间范围查询
     * @param sb
     * @param startTime
     * @param endTime
     */
    private void linkTimeSql(final StringBuilder sb,
                             final Long startTime,
                             final Long endTime) {
//        if (startTime!=null) {
//            sb.append(" and time>='" +
//                    Instant.ofEpochMilli(startTime-8*1000*60*60).toString() + "' ");
//        }
//
//        if (endTime!=null) {
//            sb.append(" and time<='" +
//                    Instant.ofEpochMilli(endTime-8*1000*60*60).toString() + "' ");
//        }
//        if (startTime!=null) {
//            sb.append(" and time>='" +
//                    DateUtils.utcTime(startTime)+ "' ");
//        }
//
//        if (endTime!=null) {
//            sb.append(" and time<='" +
//                    DateUtils.utcTime(endTime) + "' ");
//        }
        if (startTime!=null) {
            sb.append(" and time>='" +
                    Instant.ofEpochMilli(startTime).toString() + "' ");
        }

        if (endTime!=null) {
            sb.append(" and time<='" +
                    Instant.ofEpochMilli(endTime).toString() + "' ");
        }
        sb.append(" order by time asc");
    }
}
